/* Copyright (C) 2008, 2009, 2010 Faindu GmbH, Switzerland.
* All Rights Reserved. The following is Source Code and is subject to all restrictions 
* on such code as contained in the license accompanying this project. */
package blocstac.editimage.base
{
	import blocstac.api.blocbox.ImageLoader;
	import blocstac.api.blocbox.MimeType;
	import blocstac.editimage.EditImageData;
	import blocstac.editimage.EditState;
	import blocstac.util.CreateLogger;
	
	import mx.logging.ILogger;
	import mx.managers.CursorManager;

public class StateManagerImpl implements StateManager
{
	private static const LOG:ILogger = CreateLogger.withClassNameOf(StateManagerImpl)
	
	private var _undoManager:UndoManager
	private var _imageModel:ImageModel = new ImageModel()
	private var _viewModel:ViewModel = new ViewModel(_imageModel)
	private var _invalidateSize:Function
	private var _invalidateDisplayList:Function
	
	function StateManagerImpl(invalidateSize:Function, invalidateDisplayList:Function, canUndoRedoChanged:Function) {
		_invalidateSize = invalidateSize
		_invalidateDisplayList = invalidateDisplayList
		_undoManager = new UndoManager(canUndoRedoChanged)
	}
	
	//--------------------------------------------------------------------------
	//
	//  ImageModel interaction
	//
	//--------------------------------------------------------------------------	
	/** @inheritDoc */
	public function apply(op:ImageOperation):void {
		if (op) {
			CursorManager.setBusyCursor()
			op.apply(_imageModel)
			if (_imageModel.imageData) {
				_invalidateSize()
				_invalidateDisplayList()
			}
			CursorManager.removeBusyCursor()
		}
	}
	
	/** @inheritDoc */
	public function interactionStarts():Boolean {
		if (_viewModel.interactionStarts()) {
			return true
		}
		LOG.warn("other interaction has not yet finished.")
		return false
	}
	
	/** @inheritDoc */
	public function interactionEnds(op:ImageOperation):void {
		if (op) {
			CursorManager.setBusyCursor()
			op.apply(_imageModel)
			_undoManager.addOperation(op)
			CursorManager.removeBusyCursor()
		}
		_viewModel.interactionEnds()
		_invalidateSize()
		_invalidateDisplayList()
	}

	//----------------------------------
	//  editState
	//----------------------------------		
	private var _editState:EditState = EditState.zoomable
	/** @inheritDoc */
	public function switchToEditState(editState:EditState):void {
		_editState = editState
		_viewModel.switchToEditState(editState)
	}
	
	/** @inheritDoc */
	public function get editState():EditState {
		return _editState
	}
	
	//--------------------------------------------------------------------------
	//
	//  ViewModel interaction
	//
	//--------------------------------------------------------------------------
	/** @inheritDoc */
	public function updateUserViewScale(userViewScale:Number):void {
		_viewModel.updateUserViewScale(userViewScale)
		_invalidateDisplayList()
	}
	
	/** @inheritDoc */
	public function maxComponentWidthInContainer(maxComponentWidth:Number):Number {
		return _viewModel.maxComponentWidthInContainer(maxComponentWidth)
	}

	/** @inheritDoc */
	public function applyPan(relativeMoveX:Number, relativeMoveY:Number):void {
		_viewModel.applyPan(relativeMoveX, relativeMoveY)
		_invalidateDisplayList()
	}

	/** @inheritDoc */
	public function get viewModel():ViewModel {
		return _viewModel
	}
	
	//--------------------------------------------------------------------------
	//
	//  Export / Import
	//
	//--------------------------------------------------------------------------
	/** @inheritDoc */
	public function importData(editImageData:EditImageData, mimeType:MimeType):void {
		_imageModel.mimeType = mimeType
		if (editImageData) {
			EditImageDataImpl(editImageData).copyTo(_imageModel)
			_imageModel.resetHasChanged()
		}
	}

	//----------------------------------
	//  imageHasChanged
	//----------------------------------	
	/** @inheritDoc */
	public function imageHasChanged():Boolean {
		return _imageModel.hasChanged 
	}
	
	/** @inheritDoc */
	public function export(imageLoader:ImageLoader):EditImageData {
		_undoManager.reset()
		var editImageData:EditImageDataImpl = new EditImageDataImpl()
		editImageData.createFrom(_imageModel, imageLoader)
		return editImageData
	}

	//--------------------------------------------------------------------------
	//
	//  Undo / Redo
	//
	//--------------------------------------------------------------------------	
	/** @inheritDoc */
	public function undo():Boolean {
		if (_viewModel.interactionStarts()) {
			var applied:Boolean = _undoManager.undo(_imageModel)
			_viewModel.interactionEnds()
			_invalidateSize()
			_invalidateDisplayList()
			return applied
		}
		return false
	}

	/** @inheritDoc */
	public function redo():Boolean {
		if (_viewModel.interactionStarts()) {
			var applied:Boolean = _undoManager.redo(_imageModel)
			_viewModel.interactionEnds()
			_invalidateSize()
			_invalidateDisplayList()
			return applied
		}
		return false
	}
	
	/** @inheritDoc */
	public function canUndo():Boolean {
		return _undoManager.canUndo()
	}
	
	/** @inheritDoc */
	public function canRedo():Boolean {
		return _undoManager.canRedo()
	}

}
}